	
/* States for the state machine */
enum PsfreedomState {
  INIT,
  HUB_READY,
  DEVICE1_WAIT_READY,
  DEVICE1_READY,
  DEVICE1_WAIT_DISCONNECT,
  DEVICE1_DISCONNECTED,
  DEVICE2_WAIT_READY,
  DEVICE2_READY,
  DEVICE2_WAIT_DISCONNECT,
  DEVICE2_DISCONNECTED,
  DEVICE3_WAIT_READY,
  DEVICE3_READY,
  DEVICE3_WAIT_DISCONNECT,
  DEVICE3_DISCONNECTED,
  DEVICE4_WAIT_READY,
  DEVICE4_READY,
  DEVICE4_WAIT_DISCONNECT,
  DEVICE4_DISCONNECTED,
  DEVICE5_WAIT_READY,
  DEVICE5_CHALLENGED,
  DEVICE5_READY,
  DEVICE5_WAIT_DISCONNECT,
  DEVICE5_DISCONNECTED,
  DEVICE6_WAIT_READY,
  DEVICE6_READY,
  DONE,
};

#define STATUS_STR(s) (                                         \
      s==INIT?"INIT":                                           \
      s==HUB_READY?"HUB_READY":                                 \
      s==DEVICE1_WAIT_READY?"DEVICE1_WAIT_READY":               \
      s==DEVICE1_READY?"DEVICE1_READY":                         \
      s==DEVICE1_WAIT_DISCONNECT?"DEVICE1_WAIT_DISCONNECT":     \
      s==DEVICE1_DISCONNECTED?"DEVICE1_DISCONNECTED":           \
      s==DEVICE2_WAIT_READY?"DEVICE2_WAIT_READY":               \
      s==DEVICE2_READY?"DEVICE2_READY":                         \
      s==DEVICE2_WAIT_DISCONNECT?"DEVICE2_WAIT_DISCONNECT":     \
      s==DEVICE2_DISCONNECTED?"DEVICE2_DISCONNECTED":           \
      s==DEVICE3_WAIT_READY?"DEVICE3_WAIT_READY":               \
      s==DEVICE3_READY?"DEVICE3_READY":                         \
      s==DEVICE3_WAIT_DISCONNECT?"DEVICE3_WAIT_DISCONNECT":     \
      s==DEVICE3_DISCONNECTED?"DEVICE3_DISCONNECTED":           \
      s==DEVICE4_WAIT_READY?"DEVICE4_WAIT_READY":               \
      s==DEVICE4_READY?"DEVICE4_READY":                         \
      s==DEVICE4_WAIT_DISCONNECT?"DEVICE4_WAIT_DISCONNECT":     \
      s==DEVICE4_DISCONNECTED?"DEVICE4_DISCONNECTED":           \
      s==DEVICE5_WAIT_READY?"DEVICE5_WAIT_READY":               \
      s==DEVICE5_CHALLENGED?"DEVICE5_CHALLENGED":               \
      s==DEVICE5_READY?"DEVICE5_READY":                         \
      s==DEVICE5_WAIT_DISCONNECT?"DEVICE5_WAIT_DISCONNECT":     \
      s==DEVICE5_DISCONNECTED?"DEVICE5_DISCONNECTED":           \
      s==DEVICE6_WAIT_READY?"DEVICE6_WAIT_READY":               \
      s==DEVICE6_READY?"DEVICE6_READY":                         \
      s==DONE?"DONE":                                           \
      "UNKNOWN_STATE")

	  
	typedef int spinlock_t;
	struct usb_gadget {
		int speed;
		struct psfreedom_device *dev;
	};
	
	struct usb_gadget gadgeto;
	
	struct hub_port {
		u16 status;
		u16 change;
	};

	struct UsbEndpoint {
		int driverEndpointNumber;	/* Driver Endpoint number (must be filled in sequentially) */
		int endpointNumber;			/* Endpoint number (Filled in by the bus driver) */
		int transmittedBytes;		/* Number of transmitted bytes */
	};
	
	struct UsbbdDeviceRequest	{
		struct UsbEndpoint *endpoint;							/* Pointer to the endpoint to queue request on */
		void *data;												/* Pointer to the data buffer to use in the request */
		int  size;												/* Size of the data buffer */
		int  isControlRequest;									/* Is a control request? */
		void (*onComplete) (struct UsbbdDeviceRequest *req);	/* Pointer to the function to call on completion */
		int  transmitted;										/* Number of transmitted bytes  */
		int  returnCode;										/* Return code of the request, 0 == success, -3 == cancelled */
		struct UsbbdDeviceRequest *next;						/* Link pointer to next request used by the driver, set it to NULL */
		void *unused;											/* An unused value (maybe an argument) */
		void *physicalAddress;									/* Physical address */
	};
	
	static struct UsbbdDeviceRequest request;
	static struct UsbbdDeviceRequest hub_request;

	struct psfreedom_device {
														spinlock_t		lock;
														struct usb_gadget	*gadget;
		/* for control responses */ 					struct UsbbdDeviceRequest	*req;
		/* for hub interrupts */ 						struct UsbbdDeviceRequest	*hub_req;
		/* The hub uses a non standard ep2in */ 		//	struct usb_ep		*hub_ep;
		/* BULK IN for the JIG */ 						//	struct usb_ep		*in_ep;
		/* BULK OUT for the JIG */						//	struct usb_ep		*out_ep;
		/* status of the state machine */					enum PsfreedomState	status;
		/* The port to switch to after a delay */ 			int			switch_to_port_delayed;
		/* Received length of the JIG challenge */			int			challenge_len;
		/* Sent length of the JIG response */				int			response_len;
		/* Hub port status/change */						struct hub_port	hub_ports[6];
		/* Currently enabled port on the hub (0 == hub) */	unsigned int		current_port;
		/* The address of all ports (0 == hub) */			u8			port_address[7];
		/* The port1 configuration descriptor. */			u8 *port1_config_desc;
															unsigned int port1_config_desc_size;	
		/* /proc FS data */	//								struct proc_dir_entry *proc_dir;
							//								struct proc_dir_entry *proc_status_entry;
	};

	struct psfreedom_device psfreed;
	
	
	
	static int psfreedom_is_high_speed (void)	{ return 1; }
	static int psfreedom_is_low_speed (void)	{ return 0; }

	static u8 psfreedom_get_address (struct usb_gadget *g) {
		u8 address = 0;
		struct psfreedom_device *dev = &psfreed;
		if (dev->current_port != 0) { address = (0xbd800200 + 32 * dev->current_port); }
		else { address = 0xbd800200; }
		return address;
	}

	static void psfreedom_set_address (struct usb_gadget *g, u8 address) {
		int intr;
		intr = sceKernelCpuSuspendIntr();
		_sw (_lw (address) | 0x80, address);
		sceKernelCpuResumeIntr (intr);
	}
	
	struct psfreedom_device *get_gadget_data (struct usb_gadget *gadget) {
		return gadget->dev;
	}
	